<script lang="ts" setup>
import { ref, reactive, computed, watch } from "vue";
import { FormRules, FormInstance, UploadInstance, UploadFile } from "element-plus";
import { MerchantApi } from "@/Api";

interface ActionFile {
   cert?: Blob;
   cert_key?: Blob;
}

interface Props {
   modelValue: boolean;
   data?: Merchant.SearchResult;
}

const props = withDefaults(defineProps<Props>(), {
   modelValue: false
});

const emit = defineEmits<{
   (e: "update:modelValue", value: boolean): void;
}>();

const dialogVisible = computed({
   get: () => props.modelValue,
   set: value => {
      if (!value) formRef.value?.resetFields();
      emit("update:modelValue", value);
   }
});

const data = computed(() => props.data);
const loading = reactive({ add: false, form: false });
const disable = reactive({ add: false });
const actionFile = reactive<ActionFile>({
   cert: undefined,
   cert_key: undefined
});
const certRef = ref<UploadInstance>();
const certKeyRef = ref<UploadInstance>();
const formRef = ref<FormInstance>();
const form = reactive<Merchant.Update>({
   id: "",
   name: "",
   code: "",
   apiv2: "",
   apiv3: "",
   cert: "",
   cert_key: "",
   serial_no: "",
   status: "OPEN"
});

/** 表单规则 */
const formRules = reactive<FormRules>({
   name: [
      { required: true, message: "商户简称必填", trigger: "blur" },
      {
         min: 2,
         max: 20,
         message: "商户简称在 2 到 20 个字符之间",
         trigger: "change"
      }
   ],
   code: [
      { required: true, message: "商户代码必填", trigger: "blur" },
      { pattern: /^[0-9]+$/, message: "商户代码为数字", trigger: "change" }
   ],
   apiv2: { required: true, message: "APIV2 必填", trigger: "blur" },
   apiv3: { required: true, message: "APIV3 必填", trigger: "blur" },
   serial_no: { required: true, message: "证书序列号必填", trigger: "blur" },
   cert: { required: true, message: "证书文件必填", trigger: "blur" },
   cert_key: { required: true, message: "证书密钥必填", trigger: "blur" },
   status: { required: true, message: "商户状态必填", trigger: "blur" }
});

async function handlerClick(formRef?: FormInstance) {
   if (!formRef) return;

   loading.add = true;
   disable.add = true;

   await formRef.validate(async (valid, fields) => {
      if (valid) {
         const params = new FormData();

         Object.entries(form).forEach(([key, value]) => {
            params.set(key, value);
         });

         Object.entries(actionFile).forEach(([key, value]) => {
            params.set(key, value);
         });

         const res = await MerchantApi.Update(params);
         if (res.code == 200) {
            ElMessage.success("添加成功");
            dialogVisible.value = false;
         }
      }
   });

   loading.add = false;
   disable.add = false;
}

function uploadChange(type: "cert" | "cert_key", file: UploadFile) {
   actionFile[type] = file.raw;
   form[type] = file.name;
}

function handlerOpen() {
   loading.form = true;
   disable.add = true;
}
function handlerOpened() {
   if (!data.value) return;

   Object.entries(data.value).forEach(([key, value]) => {
      form[key] = value;
   });

   loading.form = false;
   disable.add = false;
}
</script>

<template>
   <el-dialog
      v-model="dialogVisible"
      ref="dialog"
      title="新增商户"
      width="500"
      draggable
      @open="handlerOpen"
      @opened="handlerOpened">
      <el-form ref="formRef" v-loading="loading.form" :model="form" :rules="formRules" label-width="110" label-position="left">
         <el-form-item label="商户状态 :" prop="status">
            <el-radio-group v-model="form.status">
               <el-radio label="OPEN">开启</el-radio>
               <el-radio label="CLOSE">关闭</el-radio>
            </el-radio-group>
         </el-form-item>
         <el-form-item label="商户简称 :" prop="name">
            <el-input v-model="form.name" placeholder="请输入商户简称" />
         </el-form-item>
         <el-form-item label="商户号 :" prop="code">
            <el-input v-model="form.code" placeholder="请输入商户号" />
         </el-form-item>
         <el-form-item label="APIV2 :" prop="apiv2">
            <el-input v-model="form.apiv2" placeholder="请输入APIV2" />
         </el-form-item>
         <el-form-item label="APIV3 :" prop="apiv3">
            <el-input v-model="form.apiv3" placeholder="请输入APIV3" />
         </el-form-item>
         <el-form-item label="证书文件 :" prop="cert">
            <el-upload
               ref="certRef"
               class="upload"
               action="#"
               :auto-upload="false"
               :show-file-list="false"
               :on-change="file => uploadChange('cert', file)">
               <template #trigger>
                  <el-input v-model="form.cert" placeholder="请上传证书文件">
                     <template #append>
                        <el-button type="primary">选择文件</el-button>
                     </template>
                  </el-input>
               </template>
            </el-upload>
         </el-form-item>
         <el-form-item label="证书密钥 :" prop="cert_key">
            <el-upload
               ref="certKeyRef"
               class="upload"
               action="#"
               :auto-upload="false"
               :show-file-list="false"
               :on-change="file => uploadChange('cert_key', file)">
               <template #trigger>
                  <el-input v-model="form.cert_key" placeholder="请上传证书密钥">
                     <template #append>
                        <el-button type="primary">选择文件</el-button>
                     </template>
                  </el-input>
               </template>
            </el-upload>
         </el-form-item>
         <el-form-item label="证书序列号 :" prop="serial_no">
            <el-input v-model="form.serial_no" placeholder="请输入证书序列号" />
         </el-form-item>
      </el-form>
      <template #footer>
         <el-button :loading="loading.add" :disabled="disable.add" type="primary" @click="handlerClick(formRef)">
            保存
         </el-button>
      </template>
   </el-dialog>
</template>

<style lang="scss" scoped>
.el-form {
   box-sizing: border-box;
   padding-inline: 20px;
}

.el-input,
.upload,
::v-deep(.el-upload) {
   width: 100%;
}
</style>
